home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 November / Macworld (1999-11).dmg / Updaters / WhiteCap 3.0.4 / WhiteCap Source.sit / WhiteCap Source / Common / General Tools / ArgList.cpp < prev    next >
C/C++ Source or Header  |  1999-07-13  |  7KB  |  427 lines

  1. #include "ArgList.h"
  2.  
  3. #include "Arg.h"
  4. #include "UtilStr.h"
  5. #include "CEgOStream.h"
  6. #include "CEgIStream.h"
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13. ArgList::ArgList() {
  14.     
  15.     mHeadArg = NULL;
  16. }
  17.  
  18.  
  19.  
  20. ArgList::~ArgList() {
  21.  
  22.     Clear();
  23. }
  24.  
  25.  
  26.  
  27.  
  28. void ArgList::Clear() {
  29.  
  30.     if ( mHeadArg ) {
  31.         delete mHeadArg;
  32.         mHeadArg = NULL;
  33.     }
  34. }
  35.  
  36.  
  37.  
  38. void ArgList::WriteTo( CEgOStream* ioStream ) {
  39.     Arg* arg = mHeadArg;
  40.     
  41.     ioStream -> PutLong( NumArgs() );
  42.     
  43.     while ( arg && ioStream -> noErr() ) {
  44.         ioStream -> PutLong( arg -> GetID() );
  45.         if ( arg -> IsStr() ) {
  46.             ioStream -> PutByte( '$' );
  47.             ((UtilStr*) arg -> GetData()) -> WriteTo( ioStream ); }
  48.         else {
  49.             ioStream -> PutByte( '#' );
  50.             ioStream -> PutLong( arg -> GetData() );
  51.         }
  52.         arg = arg -> mNext;
  53.     }    
  54. }
  55.  
  56.  
  57. void ArgList::ReadFrom( CEgIStream* ioStream ) {
  58.     long        ID, n;
  59.     UtilStr    str;
  60.     
  61.     for ( n = ioStream -> GetLong(); n > 0 && ioStream -> noErr() ; n-- ) {
  62.         ID = ioStream -> GetLong();
  63.         if ( ioStream -> GetByte() == '#' ) 
  64.             SetArg( ID, ioStream -> GetLong() );
  65.         else {
  66.             str.ReadFrom( ioStream );
  67.             SetArg( ID, str );
  68.         }
  69.     }
  70. }
  71.  
  72.  
  73.  
  74. long ArgList::NumArgs() const {
  75.     long n = 0;
  76.     Arg* arg = mHeadArg;
  77.     
  78.     while ( arg ) {
  79.         arg = arg -> mNext;
  80.         n++;
  81.     }
  82.     
  83.     return n;
  84. }
  85.  
  86.  
  87.  
  88. Arg* ArgList::FetchArg( long inID ) const {
  89.     Arg* arg = mHeadArg;
  90.     
  91.     while ( arg ) {
  92.         if ( arg -> GetID() == inID )
  93.             return arg;
  94.         arg = arg -> mNext;
  95.     }
  96.     
  97.     return NULL;
  98. }
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105. void ArgList::DeleteArg( long inArgID ) {
  106.     Arg* prev = NULL, *arg = mHeadArg;
  107.     
  108.     while ( arg ) {
  109.         if ( arg -> GetID() == inArgID ) {
  110.             if ( prev )
  111.                 prev -> mNext = arg -> mNext;
  112.             else
  113.                 mHeadArg = arg -> mNext;
  114.             arg -> mNext = NULL;
  115.             delete arg;
  116.             arg = NULL; }
  117.         else {
  118.             prev = arg;
  119.             arg = arg -> mNext;
  120.         }
  121.     }
  122. }
  123.  
  124.  
  125.  
  126. void ArgList::SetArg( long inArgID, long inArg ) {
  127.     Arg* arg = FetchArg( inArgID );
  128.     
  129.     if ( arg )
  130.         arg -> Assign( inArg );
  131.     else
  132.         mHeadArg = new Arg( inArgID, inArg, mHeadArg ); 
  133. }
  134.  
  135.  
  136.  
  137. void ArgList::SetArg( long inArgID, const UtilStr& inArg ) {
  138.     SetArg( inArgID, inArg.getCStr() );
  139. }
  140.  
  141.  
  142. void ArgList::SetArg( long inArgID, const char* inArgStr ) {
  143.     Arg* arg = FetchArg( inArgID );
  144.     
  145.     if ( arg )
  146.         arg -> Assign( inArgStr );
  147.     else
  148.         mHeadArg = new Arg( inArgID, inArgStr, mHeadArg ); 
  149. }
  150.  
  151.  
  152.  
  153.  
  154.  
  155. bool ArgList::GetArg( long inArgID, UtilStr& outStr ) const {
  156.     Arg*     arg        = FetchArg( inArgID );
  157.     
  158.     outStr.Wipe();
  159.     
  160.     if ( arg ) {
  161.          if ( arg -> IsStr() ) {
  162.              outStr.Assign( (UtilStr*) arg -> GetData() );
  163.             return true;
  164.         }
  165.     }
  166.     
  167.     return false;
  168. }
  169.  
  170.  
  171. long ArgList::GetArraySize( long inID ) const {
  172.     long i = 0;
  173.     
  174.     while ( FetchArg( IndexedID2ID( inID, i ) ) ) {
  175.         i++;
  176.     }
  177.     
  178.     return i; 
  179. }
  180.  
  181.  
  182. long ArgList::IndexedID2ID( long inBaseID, long inIndex ) {
  183.     long id = inBaseID;
  184.     
  185.  
  186.     if ( inIndex >= 100 ) {
  187.         id = ( id << 8 ) | ( ( inIndex / 100 ) + '0' );
  188.         inIndex = inIndex % 100;
  189.     }
  190.  
  191.     if ( inIndex >= 10 ) {
  192.         id = ( id << 8 ) | ( ( inIndex / 10 ) + '0' );
  193.         inIndex = inIndex % 10;
  194.     }
  195.         
  196.     id = ( id << 8 ) | ( inIndex + '0' );
  197.  
  198.     return id;
  199. }
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206. const UtilStr* ArgList::GetStr( long inArgID ) const {
  207.     Arg*     arg        = FetchArg( inArgID );
  208.     
  209.     if ( arg ) {
  210.          if ( arg -> IsStr() )
  211.             return (UtilStr*) arg -> GetData();
  212.     }
  213.     
  214.     return NULL;
  215. }
  216.  
  217.  
  218.  
  219.  
  220. double ArgList::GetFloat( long inArgID ) const {
  221.     Arg*     arg        = FetchArg( inArgID );
  222.         
  223.     if ( arg ) {
  224.         if ( arg -> IsStr() )
  225.             return ( (UtilStr*) arg -> GetData() ) -> GetFloatValue();
  226.     }
  227.     
  228.     return 0;
  229. }
  230.  
  231.  
  232.  
  233.  
  234.  
  235.     
  236. bool ArgList::GetArg( long inArgID, bool& outArg ) const {
  237.     Arg* arg = FetchArg( inArgID );
  238.     bool        found = false;
  239.     
  240.     outArg = false;
  241.     
  242.     if ( arg ) {
  243.         found = ! arg -> IsStr();
  244.         if ( found )
  245.             outArg = arg -> GetData() != 0;
  246.     }
  247.     
  248.     return found;
  249. }
  250.  
  251.  
  252.  
  253. bool ArgList::GetArg( long inArgID, long& outArg ) const {
  254.     Arg*         arg     = FetchArg( inArgID );
  255.     bool        found     = false;
  256.         
  257.     if ( arg ) {
  258.         found = ! arg -> IsStr();
  259.         if ( found )
  260.             outArg = arg -> GetData();
  261.     }
  262.     
  263.     if ( ! found )
  264.         outArg = 0;
  265.         
  266.     return found;    
  267. }
  268.     
  269.     
  270.  
  271. long ArgList::GetArg( long inArgID ) const {
  272.     Arg*         arg     = FetchArg( inArgID );
  273.         
  274.     if ( arg ) {
  275.         if ( ! arg -> IsStr() )
  276.             return arg -> GetData();
  277.         else
  278.             return ( (UtilStr*) arg -> GetData() ) -> GetValue();
  279.     }
  280.         
  281.     return 0;    
  282. }
  283.     
  284.     
  285.     
  286.  
  287. void ArgList::SetArgs( const ArgList& inArgs ) {
  288.     Arg* arg = inArgs.mHeadArg;
  289.     long data;
  290.     long id;
  291.     
  292.     while ( arg ) {
  293.         id =  arg -> GetID();
  294.         data = arg -> GetData();
  295.         if ( arg -> IsStr() ) 
  296.             SetArg( id, (UtilStr*) data );
  297.         else 
  298.             SetArg( id, data );
  299.         arg = arg -> mNext;
  300.     }
  301. }
  302.  
  303.  
  304.     
  305. void ArgList::SetArgs( const char* curPtr, long inLen ) {
  306.     const char* lastPtr;
  307.     const char* endPtr = curPtr;
  308.     long ID;
  309.     bool terminated, isStr;
  310.     UtilStr    s;
  311.     
  312.     if ( inLen > 0 ) 
  313.         endPtr = curPtr + inLen;
  314.     else {
  315.         endPtr = curPtr;
  316.         while ( *endPtr )
  317.             endPtr++;
  318.     }
  319.     
  320.     do {                                        // Loop thru each arg in the str
  321.         terminated    = true;
  322.         
  323.         // When we're not inside a string, igrore oddball/whitespace chars (chars <= 32)
  324.         while ( curPtr < endPtr && *curPtr <= ' ' )
  325.             curPtr++;
  326.         lastPtr = curPtr;
  327.  
  328.             
  329.         while ( curPtr < endPtr && ( *curPtr != cArgSeparator || ! terminated ) ) {
  330.             if ( *curPtr == '"' )
  331.                 terminated = ! terminated;        // Toggle string acceptance
  332.             curPtr++;
  333.         }
  334.         
  335.         // Extract the 4 byte ID...
  336.         ID = 0;
  337.         while ( *lastPtr != '=' && *lastPtr != '-' && curPtr > lastPtr ) {
  338.             ID = (ID << 8) | ((unsigned long) *lastPtr);
  339.             lastPtr++;
  340.         }
  341.         lastPtr++;                    // Skip the '='
  342.         isStr = *lastPtr == '\"';    // This arg is a string if we see a "
  343.         if ( curPtr > lastPtr ) {
  344.             if ( isStr ) {
  345.                 s.Wipe();
  346.                 s.AppendFromMeta( lastPtr, curPtr - lastPtr );
  347.                 SetArg( ID, s ); }
  348.             else {
  349.                 s.Assign( lastPtr, curPtr - lastPtr );
  350.                 SetArg( ID, s.GetValue() );
  351.             }
  352.         }
  353.         curPtr++;
  354.     } while ( curPtr < endPtr );
  355. }
  356.  
  357.  
  358.  
  359. void ArgList::SetArgs( CEgIStream* inStream ) {
  360.     UtilStr str, configText;
  361.     long numQuotes, pos, i, end;
  362.     
  363.     
  364.     if ( inStream -> noErr() ) { 
  365.     
  366.         // Read and chuck any comments
  367.         while ( inStream -> noErr() ) {
  368.             inStream -> Readln( str );
  369.             pos = 1;
  370.             numQuotes = 0;
  371.             do {
  372.                 i = str.contains( "//", 2, pos - 1 );
  373.                 for ( ; pos <= i; pos++ ) {
  374.                     if ( str.getChar( pos ) == '\"' )
  375.                         numQuotes++;
  376.                 }
  377.             } while ( numQuotes % 2 == 1 && i > 0 );
  378.             
  379.             if ( i > 0 )
  380.                 str.Keep( i - 1 );
  381.             configText.Append( str );
  382.         } 
  383.         inStream -> throwErr( cNoErr );
  384.         
  385.         // Remove block comments
  386.         do {
  387.             i = configText.contains( "/*" );
  388.             if ( i > 0 ) {
  389.                 end = configText.contains( "*/" );
  390.                 if ( end > 0 )
  391.                     configText.Remove( i, end - i + 2 );
  392.             }
  393.         } while ( i > 0 && end > 0 );
  394.         
  395.         // Parse the args/dict...
  396.         SetArgs( configText );
  397.     }
  398. }
  399.  
  400.  
  401.  
  402.  
  403.  
  404. void ArgList::ExportTo( UtilStr& ioStr, bool inLineBreaks ) const {
  405.     CEgOStream ostream;
  406.     
  407.     ExportTo( &ostream, inLineBreaks );
  408.     ostream.mOBuf.Swap( ioStr );
  409. }    
  410.  
  411.  
  412.  
  413. void ArgList::ExportTo( CEgOStream* ioStream, bool inLineBreaks ) const {
  414.     Arg* arg = mHeadArg;
  415.     
  416.     while (arg) {
  417.         arg -> ExportTo( ioStream );
  418.         arg = arg -> mNext;
  419.         if ( arg ) {
  420.             ioStream -> PutByte( cArgSeparator );
  421.             if ( inLineBreaks )
  422.                 ioStream -> Writeln();
  423.         }
  424.     }
  425. }    
  426.  
  427.